package com.markhsiu.minimq.remote.transport.talentaio.handler;

import java.nio.ByteBuffer;

import com.markhsiu.minimq.remote.transport.talentaio.MessagePacket;
import com.talent.aio.common.ChannelContext;
import com.talent.aio.common.GroupContext;
import com.talent.aio.common.exception.AioDecodeException;
import com.talent.aio.common.intf.AioHandler;

/**
 * 服务器端和客户端的编码解码算法
 * @author Mark Hsiu
 *
 */
public abstract class MessageAbsAioHandler implements AioHandler<Object, MessagePacket, Object>{ 

	@Override
	public ByteBuffer encode(MessagePacket packet, GroupContext<Object, MessagePacket, Object> groupContext, ChannelContext<Object, MessagePacket, Object> channelContext){
		byte[] body = packet.getBody();
		int bodyLen = 0;
		if(body != null){
			bodyLen = body.length;
		}
		
		int allLen = MessagePacket.HEADER_LENGHT + bodyLen;
		ByteBuffer buffer = ByteBuffer.allocate(allLen);
		buffer.order(groupContext.getByteOrder());
		
		buffer.putInt(bodyLen);
		if(bodyLen > 0 ){
			buffer.put(body);
		}
		return buffer;
	}

	@Override
	public MessagePacket decode(ByteBuffer buffer, ChannelContext<Object, MessagePacket, Object> channelContext) 
			throws AioDecodeException {
		int readableLen = buffer.limit() - buffer.position();
		if(readableLen < MessagePacket.HEADER_LENGHT){
			return null;
		}
		
		int bodyLen = buffer.getInt();
		if(bodyLen < 0){
			throw new AioDecodeException("bodyLength [" + bodyLen + "] is not right, remote:" + channelContext.getClientNode());
		}
		
		int neededLen = MessagePacket.HEADER_LENGHT + bodyLen;
		int check = readableLen - neededLen;
		if(check < 0){//不够消息体长度（剩下的buffer组不了消息体）
			return null;
		}
		
		MessagePacket packet = new MessagePacket();
		if(bodyLen > 0){
			byte[] dst = new byte[bodyLen];
			buffer.get(dst);
			packet.setBody(dst);
		}
		return packet;	
	}
}
